package com.seqb.system.shiro;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.seqb.common.utils.JwtUtils;
import com.seqb.manage.menu.service.MenuService;
import com.seqb.manage.user.dao.UserDao;
import com.seqb.manage.user.domain.UserDO;
import com.seqb.system.domain.JwtToken;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * @author lilinshen
 * @title 请填写标题
 * @description 请填写相关描述
 * @date 2019/11/26
 */
@Component
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserDao userDao;
    @Autowired
    private MenuService menuService;

    /**
     * 必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 用户授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String account = JwtUtils.getAccount(principals.toString());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("account", account);
        UserDO user = userDao.selectOne(queryWrapper);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        if (null != user) {
            Set<String> perms = menuService.listPerms(user.getId());
            simpleAuthorizationInfo.setStringPermissions(perms);
        }
        return simpleAuthorizationInfo;
    }

    /**
     * 用户认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
        String token = (String) auth.getCredentials();
        if (StringUtils.isEmpty(token)) {
            throw new AuthenticationException("token不能为空！(empty)");
        }
        String account = JwtUtils.getAccount(token);
        if (account == null) {
            throw new AuthenticationException("token无效！(invalid)");
        }
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("account", account);
        UserDO user = userDao.selectOne(queryWrapper);
        if (user == null) {
            throw new AuthenticationException("账号不存在！(no-user)");
        }
        if ("0".equals(user.getState())) {
            throw new AuthenticationException("账号已被锁定！(locked)");
        }
        int verify = JwtUtils.verify(token, account, user.getPassword());
        if (verify == 2) {
            throw new AuthenticationException("token超时失效！(expired)");
        } else if (verify == 3) {
            throw new AuthenticationException("账号或密码错误！(signature)");
        } else if (verify == 4) {
            throw new AuthenticationException("jwt认证失败！(fail)");
        }
        return new SimpleAuthenticationInfo(token, token, "user_realm");
    }

}
